//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Query Application Block
//===============================================================================

using System;
using System.ComponentModel;
using System.Drawing.Design;
using Microsoft.Practices.EnterpriseLibrary.Configuration.Design;

namespace EntLibContrib.Query.Configuration.Design
{
  /// <summary>
	/// Represents a <see cref="QueryData"/> configuration element.
	/// This class is abstract.
  /// </summary>
	public abstract class QueryNode : QueryBaseNode
	{
		#region Fields
		private CommandNode customCommandNode;
		private EventHandler<ConfigurationNodeChangedEventArgs> onCustomCommandNodeRemoved;
		private EventHandler<ConfigurationNodeChangedEventArgs> onCustomCommandNodeRenamed;
		private ParameterSetNode parameterSetNode;
		private EventHandler<ConfigurationNodeChangedEventArgs> onParameterSetNodeRemoved;
		private EventHandler<ConfigurationNodeChangedEventArgs> onParameterSetNodeRenamed;
		private string customCommandName;
		private string parameterSetName;
		#endregion

		#region Properties
		/// <summary>
		/// Gets or sets the name of the custom command.
		/// </summary>
		/// <value>The name of the custom command.</value>
		[Browsable(false)]
		public string CustomCommandName
		{
			get { return customCommandName; }
			set { customCommandName = value; }
		}

		/// <summary>
		/// Gets or sets the name of the parameter set.
		/// </summary>
		/// <value>The name of the parameter set.</value>
		[Browsable(false)]
		public string ParameterSetName
		{
			get { return parameterSetName; }
			set { parameterSetName = value; }
		}

		/// <summary>
		/// Gets or sets the name of the custom command.
		/// </summary>
		/// <value>The name of the custom command.</value>
		[Browsable(false)]
		public CommandNode CustomCommand
		{
			get { return customCommandNode; }
			set
			{
				customCommandNode = LinkNodeHelper.CreateReference<CommandNode>(customCommandNode,
																																				value,
																																				onCustomCommandNodeRemoved,
																																				onCustomCommandNodeRenamed);
				customCommandName = (null == customCommandNode) ? string.Empty : customCommandNode.Name;
			}
		}

		/// <summary>
		/// Gets the name of the parameter set to use for this query.
		/// </summary>
		/// <value>The name of the parameter set to use for this query.</value>
		[Editor(typeof(ReferenceEditor), typeof(UITypeEditor))]
		[ReferenceType(typeof(ParameterSetNode))]
		[QueryCategory("CategoryProvider")]
		[QueryDescription("QueryParameterSetNameDescription")]
		public ParameterSetNode ParameterSet
		{
			get { return parameterSetNode; }
			set
			{
				parameterSetNode = LinkNodeHelper.CreateReference<ParameterSetNode>(parameterSetNode,
																																						value,
																																						onParameterSetNodeRemoved,
																																						onParameterSetNodeRenamed);
				parameterSetName = (null == parameterSetNode) ? string.Empty : parameterSetNode.Name;
			}
		}

		/// <summary>
		/// Gets or sets the on custom command node removed.
		/// </summary>
		/// <value>The on custom command node removed.</value>
		protected EventHandler<ConfigurationNodeChangedEventArgs> OnCustomCommandNodeRemoved
		{
			get { return onCustomCommandNodeRemoved; }
			set { onCustomCommandNodeRemoved = value; }
		}

		/// <summary>
		/// Gets or sets the on custom command node renamed.
		/// </summary>
		/// <value>The on custom command node renamed.</value>
		protected EventHandler<ConfigurationNodeChangedEventArgs> OnCustomCommandNodeRenamed
		{
			get { return onCustomCommandNodeRenamed; }
			set { onCustomCommandNodeRenamed = value; }
		}
		#endregion

		#region Construction
		/// <summary>
		/// Initialize a new instance of the <see cref="QueryNode"/> class.
		/// </summary>
		protected QueryNode ()
    {
			this.onCustomCommandNodeRemoved = new EventHandler<ConfigurationNodeChangedEventArgs>(OnCustomCommandNodeRemovedHandler);
			this.onCustomCommandNodeRenamed = new EventHandler<ConfigurationNodeChangedEventArgs>(OnCustomCommandNodeRenamedHandler);
			this.onParameterSetNodeRemoved = new EventHandler<ConfigurationNodeChangedEventArgs>(OnParameterSetNodeRemovedHandler);
			this.onParameterSetNodeRenamed = new EventHandler<ConfigurationNodeChangedEventArgs>(OnParameterSetNodeRenamedHandler);
		}
		#endregion

		#region Protected Methods
		/// <summary>
		/// Releases the unmanaged resources used by the <see cref="QueryNode "/> and optionally releases the managed resources.
		/// </summary>
		/// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.</param>
		protected override void Dispose(bool disposing)
		{
			try
			{
				if (disposing)
				{
					if (customCommandNode != null)
					{
						customCommandNode.Removed -= onCustomCommandNodeRemoved;
						customCommandNode.Renamed -= onCustomCommandNodeRenamed;
					}
					if (parameterSetNode != null)
					{
						parameterSetNode.Removed -= onParameterSetNodeRemoved;
						parameterSetNode.Renamed -= onParameterSetNodeRenamed;
					}
				}
			}
			finally
			{
				base.Dispose(disposing);
			}
		}
		#endregion

		#region Private Methods
		private void OnCustomCommandNodeRemovedHandler(object sender, ConfigurationNodeChangedEventArgs e)
		{
			customCommandNode = null;
		}

		private void OnCustomCommandNodeRenamedHandler(object sender, ConfigurationNodeChangedEventArgs e)
		{
			customCommandName = e.Node.Name;
		}

		private void OnParameterSetNodeRemovedHandler(object sender, ConfigurationNodeChangedEventArgs e)
		{
			parameterSetNode = null;
		}

		private void OnParameterSetNodeRenamedHandler(object sender, ConfigurationNodeChangedEventArgs e)
		{
			parameterSetName = e.Node.Name;
		}
		#endregion
	}
}